package frame

import (
	"fmt"
	"gitee.com/jamon/espoir_go/common"
	"gitee.com/jamon/espoir_go/common/utils"
	"sync"
)

//type User struct {
//	UserID    uint64
//	SessionID string
//	Extra     map[string]interface{}
//}

type User = common.User

type UserManager struct {

	// userID: user
	userInfo utils.Map[uint64, *User]

	// sessionID: user
	sessionInfo utils.Map[string, *User]
}

var (
	userMgr  *UserManager
	userOnce sync.Once
)

func GetUserManager() *UserManager {
	userOnce.Do(func() {
		userMgr = &UserManager{
			userInfo:    utils.NewMap[uint64, *User](),
			sessionInfo: utils.NewMap[string, *User](),
		}
	})
	return userMgr
}

func (mgr *UserManager) GetUserByUserID(userID uint64) (user *User, err error) {
	user, _ = mgr.userInfo.Get(userID)
	if user == nil {
		err = fmt.Errorf("user not found, userID: %d", userID)
		return
	}
	return
}

func (mgr *UserManager) GetUserBySessionID(sessionID string) (user *User, err error) {
	user, _ = mgr.sessionInfo.Get(sessionID)
	if user == nil {
		err = fmt.Errorf("user not found, sessionID: %s", sessionID)
		return
	}
	return
}

func (mgr *UserManager) AddUser(user *User) (err error) {
	_, exist := mgr.userInfo.Get(user.UserID)
	if exist {
		return fmt.Errorf("user already exists, userID: %d", user.UserID)
	}
	mgr.userInfo.Put(user.UserID, user)
	mgr.sessionInfo.Put(user.SessionID, user)
	return
}

func (mgr *UserManager) RemoveUserByUserID(userID uint64) (err error) {
	user, err := mgr.GetUserByUserID(userID)
	if err != nil {
		return
	}
	mgr.userInfo.Remove(userID)
	mgr.sessionInfo.Remove(user.SessionID)
	return
}

func (mgr *UserManager) UpdateSession(newSessionID string, userID uint64) (err error) {
	user, err := mgr.GetUserByUserID(userID)
	if err != nil {
		return
	}
	mgr.sessionInfo.Remove(user.SessionID)
	user.SessionID = newSessionID
	mgr.sessionInfo.Put(newSessionID, user)
	return
}
